Technical Q&A QA1325
Creating an OpenGL texture from an NSView


Q: NSView ‚©‚ç OpenGL ƒeƒNƒXƒ`ƒƒ‚ðì¬‚·‚é‚ɂ͂ǂ¤‚·‚ê‚΂悢‚̂łµ‚傤‚©B

AF ‚Ù‚Æ‚ñ‚Ç‚·‚×‚Ä‚Ì NSView ‚¨‚æ‚Ñ‚»‚̃TƒuƒNƒ‰ƒX‚ð OpenGL ‚ŃeƒNƒXƒ`ƒƒ‚Æ‚µ‚ÄŽg—p‚Å‚«‚Ü‚·B‚»‚ÌŠî–{ƒvƒƒZƒX‚ɂ́ANSBitmapImageRep ‚ðŽg—p‚µ‚Ä NSView ‚̃Cƒ[ƒWƒf[ƒ^‚ð OpenGL ‚ŃeƒNƒXƒ`ƒƒƒf[ƒ^‚Æ‚µ‚Ä‚·‚®‚ÉŽg—p‚Å‚«‚éŒ`Ž®‚ÅŠi”[‚·‚邱‚Æ‚ªŠÜ‚Ü‚ê‚Ü‚·BŽŸ‚̎菇‚Å‚±‚Ì•û–@‚ð‚æ‚èÚ×‚É‹K’肵‚Ü‚·B

  • NSBitmapImageRep ‚ðƒeƒNƒXƒ`ƒƒƒf[ƒ^‚ÌŠi”[‚ÉŽg—p‚·‚邽‚߂Ɋ„‚è“–‚Ă܂·B
  • -initWithFocusedViewRect: ƒƒ\ƒbƒh‚Æ NSView -bounds ƒƒ\ƒbƒh‚ðŽg—p‚µ‚āANSBitmapImageRep ‚ð‰Šú‰»‚µ‚Ü‚·B
  • NSBitmapImageRep ƒƒ\ƒbƒh‚Ì -bitmapData ‚ðŽg—p‚µ‚ÄŽÀÛ‚̃sƒNƒZƒ‹ƒf[ƒ^‚ðŽæ‚èo‚µA‚±‚ê‚ð OpenGL ‚ɁA“KØ‚ȃpƒ‰ƒ[ƒ^‚ƂƂà‚ɃeƒNƒXƒ`ƒƒ‚Æ‚µ‚Ä“n‚µ‚Ü‚·B

ƒŠƒXƒg 1 ‚́AŽÀÛ‚É‚±‚̃eƒNƒjƒbƒN‚ðŽg—p‚·‚鎩ŒÈŠ®Œ‹Œ^ Cocoa ƒƒ\ƒbƒh‚ðŽ¦‚µ‚Ä‚¢‚Ü‚·B

ƒŠƒXƒg 1. NSView ‚©‚ç‚Ì OpenGL ƒeƒNƒXƒ`ƒƒ‚̍쐬

// Œ»Ý‚Ì OpenGL ƒRƒ“ƒeƒLƒXƒg“à‚Ì 'theView' ‚©‚ç 'texName' ƒeƒNƒXƒ`ƒƒ‚𐶐¬
-(void)textureFromView:(NSView*)theView textureName:(GLuint*)texName
{
    // ƒ\[ƒXƒrƒ…[‚©‚çƒrƒbƒgƒ}ƒbƒv‚𐶐¬
    NSBitmapImageRep * bitmap = [NSBitmapImageRep alloc];
    int samplesPerPixel = 0;
    
    [theView lockFocus];
    [bitmap initWithFocusedViewRect:[theView bounds]];
    [theView unlockFocus];

    // “ǂݎæ‚éƒrƒbƒgƒ}ƒbƒv‚Ì“KØ‚ȍs‚Ì’·‚³‚ðÝ’è
    glPixelStorei(GL_UNPACK_ROW_LENGTH, [bitmap pixelsWide]);

    // “ǂݎæ‚é”z—ñ‚̃oƒCƒg”‚ðÝ’è (ƒrƒbƒgƒ}ƒbƒv‚̃sƒNƒZƒ‹‚ ‚½‚è 3 ƒoƒCƒg•K—v)
    glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
    // ƒeƒNƒXƒ`ƒƒ‚ª“n‚³‚ê‚È‚¢ê‡‚́AV‚µ‚¢ƒeƒNƒXƒ`ƒƒƒIƒuƒWƒFƒNƒg‚𐶐¬
    if (*texName == 0)
         glGenTextures (1, texName);
     glBindTexture (GL_TEXTURE_RECTANGLE_EXT, *texName);
    // ƒ~ƒbƒvƒ}ƒbƒv‚È‚µ‚̃tƒBƒ‹ƒ^ˆ— (texture_rectangle ‚ɂ͏璷)
    glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, 
                    GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    samplesPerPixel = [bitmap samplesPerPixel];

    // ”ñ PlanerARGB 24 ƒrƒbƒgƒrƒbƒgƒ}ƒbƒvA‚Ü‚½‚Í RGBA 32 ƒrƒbƒgƒrƒbƒgƒ}ƒbƒv
    if(![bitmap isPlanar] && 
       (samplesPerPixel == 3 || samplesPerPixel == 4)) { 
         glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 
                      0, 
                      samplesPerPixel == 4 ? GL_RGBA8 : GL_RGB8,
                      [bitmap pixelsWide], 
                      [bitmap pixelsHigh], 
                      0, 
                      samplesPerPixel == 4 ? GL_RGBA : GL_RGB,
                      GL_UNSIGNED_BYTE, 
                      [bitmap bitmapData]);
    } else {
    /*
        ƒGƒ‰[ó‘Ô...
        ã‚̃R[ƒh‚Å‚Í 2 ‚‚̃P[ƒX (24 ƒrƒbƒg RGBA‚¨‚æ‚Ñ 32 ƒrƒbƒg RGBA) ‚ªˆ—‚³‚ê‚Ä‚¨‚èA
        •K—v‚Å‚ ‚ê‚΁A‚Ù‚©‚̃rƒbƒgƒ}ƒbƒvŒ`Ž®‚̃Tƒ|[ƒg‚à‰Â”\B
        
        ‚¢‚­‚‚©‚Ì—L—p‚ȏî•ñ‚ðƒƒO‚ɏ‘‚«o‚·B
    */
        NSLog (@"-textureFromView: Unsupported bitmap data
        format: isPlanar:%d, samplesPerPixel:%d, bitsPerPixel:%d,
        bytesPerRow:%d, bytesPerPlane:%d",
            [bitmap isPlanar], 
            [bitmap samplesPerPixel], 
            [bitmap bitsPerPixel], 
            [bitmap bytesPerRow], 
            [bitmap bytesPerPlane]);
    }
    // ƒNƒŠ[ƒ“ƒAƒbƒvˆ—
    [bitmap release];
}

ã‚̃R[ƒh‚ðŒŸ“¢‚·‚éÛAˆÈ‰º‚Ì“_‚É’ˆÓ‚·‚é•K—v‚ª‚ ‚è‚Ü‚·B

  • GL_EXT_texture_rectangle ‚́ARage128 ‚ŃTƒ|[ƒg‚³‚ê‚Ä‚¢‚È‚¢A2 ‚‚̃eƒNƒXƒ`ƒƒ‚ðƒTƒ|[ƒg‚·‚邽‚߂Ɏg—p‚³‚ê‚Ü‚·B
  • gluScaleImage() ‚́AGL_EXT_texture_rectangle ‚ðƒTƒ|[ƒg‚µ‚È‚¢ƒn[ƒhƒEƒFƒA—p‚ɁA”ñ PoT ƒeƒNƒXƒ`ƒƒ‚ð PoT ƒTƒCƒY‚ÖƒXƒP[ƒ‹ˆ—‚·‚邽‚߂Ɏg—p‚Å‚«‚Ü‚·B
  • —LŒø‚ÈŒ»Ý‚Ì OpenGL ƒRƒ“ƒeƒLƒXƒg‚ª•K—v‚Å‚·B
  • ‚±‚ÌŽí—Þ‚Ì‘€ì‚ł́A‹@”\‚µ‚È‚¢ƒrƒ…[‚ª‚ ‚è‚Ü‚·BŒ»Žž“_‚ł́A‚±‚ê‚ç‚̃rƒ…[‚É‚Í NSProgressIndicatorANSMovieViewANSOpenGLView ‚ª‚ ‚è‚Ü‚·BinitWithFocusedViewRect: ‚́A‚±‚ê‚ç‚̃rƒ…[‚ªŽg—p‚µ‚È‚¢AƒEƒCƒ“ƒhƒEƒoƒbƒLƒ“ƒOƒXƒgƒA‚©‚ç“ǂݍž‚Ü‚ê‚Ü‚·B•`‰æ‚ɕʂ̃T[ƒtƒFƒX‚ðŽg—p‚·‚邱‚ê‚ç‚̃rƒ…[‚́AinitWithFocusedViewRect: ‚ɂ͓ǂݎæ‚ê‚Ü‚¹‚ñB

[2004 ”N 2 ŒŽ 13 “ú]